package info.batcloud.fanli.core.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.aliyun.opensearch.SearcherClient;
import com.aliyun.opensearch.sdk.dependencies.com.google.common.collect.Lists;
import com.aliyun.opensearch.sdk.generated.search.*;
import com.aliyun.opensearch.sdk.generated.search.general.SearchResult;
import com.ctospace.archit.common.pagination.Paging;
import com.taobao.api.ApiException;
import com.taobao.api.TaobaoClient;
import com.taobao.api.request.TbkItemInfoGetRequest;
import com.taobao.api.response.TbkItemInfoGetResponse;
import info.batcloud.fanli.core.aliyun.OpenSearchConfig;
import info.batcloud.fanli.core.aliyun.opensearch.SearchResponse;
import info.batcloud.fanli.core.constants.TaobaoClientConstants;
import info.batcloud.fanli.core.dto.CommissionItemDTO;
import info.batcloud.fanli.core.dto.CommissionItemFetchDTO;
import info.batcloud.fanli.core.dto.CommissionItemSearchDTO;
import info.batcloud.fanli.core.dto.ShopcatDTO;
import info.batcloud.fanli.core.enums.EcomPlat;
import info.batcloud.fanli.core.enums.SearchFrom;
import info.batcloud.fanli.core.enums.TbkDgMaterialOptionalSort;
import info.batcloud.fanli.core.item.collection.*;
import info.batcloud.fanli.core.service.*;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import javax.inject.Inject;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class CommissionItemSearchServiceImpl implements CommissionItemSearchService {

    private static final Logger logger = LoggerFactory.getLogger(CommissionItemSearchServiceImpl.class);

    @Inject
    private SearcherClient searcherClient;

    @Inject
    private OpenSearchConfig openSearchConfig;

    @Inject
    private SystemSettingService systemSettingService;

    @Inject
    private CommissionItemService commissionItemService;

    @Inject
    private ShopcatService shopcatService;

    @Inject
    private TbkDgMaterialOptionalSelectionCollector tbkDgMaterialOptionalCollector;

    @Inject
    private TbkDgOptimusMaterialSelectionCollector tbkDgOptimusMaterialSelectionCollector;

    @Inject
    private JdQueryCouponGoodsSelectionCollector jdQueryCouponGoodsCollector;

    @Inject
    private DdkGoodsSearchSelectionCollector ddkGoodsSearchCollector;

    @Inject
    private CommissionService commissionService;

    @Inject
    @Qualifier(TaobaoClientConstants.TAOBAO_CLIENT_ITEM_TBK)
    private TaobaoClient taobaoClient;

    @Override
    public Paging<CommissionItemSearchDTO> search(SearchParam param) {
        SearchFrom searchFrom = param.getSearchFrom();
        if (searchFrom == null) {
            searchFrom = SearchFrom.SITE;
        }

        if (StringUtils.isNotBlank(param.getKeywords())) {
            try {
                param.setKeywords(URLDecoder.decode(param.getKeywords(), "utf8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        Paging<CommissionItemSearchDTO> paging;
        switch (searchFrom) {
            case TAOBAO:
                paging = searchTaobao(param);
                break;
            case JD:
                paging = searchJD(param);
                break;
            case PDD:
                paging = searchPdd(param);
                break;
            default:
                paging = searchSite(param);
                break;
        }

        List<String> itemIdList = null;
        List<CommissionItemSearchDTO> priorList = null;
        //如果指定了itemIds，那么itemId的商品需要优先显示，在第一页的时候
        if (StringUtils.isNotBlank(param.getItemIds()) && param.getPage() == 1) {
            itemIdList = Arrays.asList(param.getItemIds().split(","));
        }
        for (CommissionItemSearchDTO dto : paging.getResults()) {
            dto.setShareCommission(commissionItemService.findShareCommission(dto.getPrice(), dto.getCommissionRate()));
            dto.setRewardShareCommission(commissionService.determineRewardCommissionFee(dto.getShareCommission()));
            if (itemIdList != null) {
                if (itemIdList.contains(dto.getId() + "")) {
                    if (priorList == null) {
                        priorList = new ArrayList<>();
                    }
                    priorList.add(dto);
                }
            }
        }
        //对优先排序的priorList进行处理
        if (priorList != null) {
            final List<String> idList = itemIdList;
            Collections.sort(priorList, Comparator.comparingInt(o -> -idList.indexOf(o.getId() + "")));
            for (CommissionItemSearchDTO dto : priorList) {
                paging.getResults().remove(dto);
                paging.getResults().add(0, dto);
            }
        }

        return paging;
    }

    private Paging<CommissionItemSearchDTO> searchJD(SearchParam param) {
        JdQueryCouponGoodsSelectionCollector.JdQueryCouponGoodsContext context = new JdQueryCouponGoodsSelectionCollector.JdQueryCouponGoodsContext();
        context.setGoodsKeyword(param.getKeywords());
        context.setMaxPage(1);
        context.setPageSize(param.getPageSize());
        context.setStartPage(param.getPage());
        if (StringUtils.isNotBlank(param.getCatIds())) {
            long catId = Long.valueOf(param.getCatIds().split(",")[0]);
            ShopcatDTO shopcatDTO = shopcatService.findRealById(catId);
            if (shopcatDTO.getJdCatId() != null) {
                context.setCid3(shopcatDTO.getJdCatId());
            }
        }
        if (param.getStartPrice() != null) {
            context.setPriceFrom(param.getStartPrice());
        }
        if (param.getEndPrice() != null) {
            context.setPriceTo(param.getEndPrice());
        }
        Paging<CommissionItemSearchDTO> paging = Paging.empty(param.getPageSize());
        jdQueryCouponGoodsCollector.collect(context, resultPaging -> bindToCommissionItemSearchBOPaging(paging, resultPaging));
        logger.info("京东优惠券直接查询完成，总返回数量:" + paging.getResults().size());
        return paging;
    }

    private Paging<CommissionItemSearchDTO> searchPdd(SearchParam param) {
        DdkGoodsSearchCollectContext context = new DdkGoodsSearchCollectContext();
        context.setKeyword(param.getKeywords());
        context.setMaxPage(1);
        context.setPageSize(param.getPageSize());
        context.setStartPage(param.getPage());
        if (StringUtils.isNotBlank(param.getCatIds())) {
            long catId = Long.valueOf(param.getCatIds().split(",")[0]);
            ShopcatDTO shopcatDTO = shopcatService.findRealById(catId);
            if (shopcatDTO.getJdCatId() != null) {
                context.setCatId(shopcatDTO.getPddCatId());
            }
        }
        if (param.getCoupon() != null && param.getCoupon()) {
            context.setWithCoupon(param.getCoupon());
        }
        switch (param.getSort()) {
            case NONE:
                break;
            case PRICE_ASC:
                context.setSortType(3);
                break;
            case PRICE_DESC:
                context.setSortType(4);
                break;
            case SALES_DESC:
                context.setSortType(6);
                break;
            case LIST_TIME_DESC:
                context.setSortType(12);
                break;
            case COMMISSION_VALUE_DESC:
                context.setSortType(14);
                break;
        }
        Paging<CommissionItemSearchDTO> paging = Paging.empty(param.getPageSize());
        ddkGoodsSearchCollector.collect(context, resultPaging -> bindToCommissionItemSearchBOPaging(paging, resultPaging));
        logger.info("拼多多优惠券直接查询完成，总返回数量:" + paging.getResults().size());
        return paging;
    }

    private Paging<CommissionItemSearchDTO> searchTaobao(SearchParam param) {
        Paging<CommissionItemSearchDTO> paging = Paging.empty(param.getPageSize());
        if (param.getTaobaoMaterialId() != null) {
            TbkDgOptimusMaterialContext context = new TbkDgOptimusMaterialContext();
            context.setMaterialId(param.getTaobaoMaterialId());
            context.setStartPage(param.getPage());
            context.setMaxPage(param.getPage());
            tbkDgOptimusMaterialSelectionCollector.collect(context,
                    resultPaging -> bindToCommissionItemSearchBOPaging(paging, resultPaging));
        } else {
            TbkDgMaterialOptionalCollectContext context = new TbkDgMaterialOptionalCollectContext();
            context.setQ(param.getKeywords());
            context.setSort(TbkDgMaterialOptionalSort.TOTAL_SALES_DES);
            context.setMaxPage(1);
            context.setPageSize(param.getPageSize());
            context.setStartPage(param.getPage());
            if (param.getTbkZt() != null && param.getTbkZt()) {
                /**
                 * 营销主推商品
                 * */
                context.setMaterialId(6268L);
            }
            if (param.getCoupon() != null && param.getCoupon()) {
                context.setHasCoupon(param.getCoupon());
            }
            switch (param.getSort()) {
                case NONE:
                    break;
                case PRICE_ASC:
                    context.setSort(TbkDgMaterialOptionalSort.PRICE_ASC);
                    break;
                case PRICE_DESC:
                    context.setSort(TbkDgMaterialOptionalSort.PRICE_DES);
                    break;
                case SALES_DESC:
                    context.setSort(TbkDgMaterialOptionalSort.TOTAL_SALES_DES);
                    break;
                case LIST_TIME_DESC:
                    break;
                case COMMISSION_VALUE_DESC:
                    context.setSort(TbkDgMaterialOptionalSort.TK_RATE_DES);
                    break;
            }
            if (param.getTaobaoMaterialId() != null) {
                context.setMaterialId(param.getTaobaoMaterialId());
            }
            if (param.getStartPrice() != null) {
                context.setStartPrice(param.getStartPrice());
            }
            if (param.getEndPrice() != null) {
                context.setEndPrice(param.getEndPrice());
            }
            if (param.getFreeShipment() != null && param.getFreeShipment()) {
                context.setNeedFreeShipment(true);
            }
            if (StringUtils.isNotBlank(param.getCatIds())) {
                long catId = Long.valueOf(param.getCatIds().split(",")[0]);
                ShopcatDTO shopcatDTO = shopcatService.findRealById(catId);
                if (shopcatDTO.getTaobaoCatId() != null) {
                    context.setCat(shopcatDTO.getTaobaoCatId() + "");
                    context.setShopcatId(catId);
                }
            }
            if (param.getEcomPlat() != null) {
                context.setTmall(param.getEcomPlat() == EcomPlat.TMALL);
            }
            tbkDgMaterialOptionalCollector.collect(context, resultPaging -> bindToCommissionItemSearchBOPaging(paging, resultPaging));
            Map<String, CommissionItemSearchDTO> map = new HashMap<>(20);
            List<String> itemIds = paging.getResults().stream().map(ci -> {
                String id = ci.getSourceItemId().toString();
                map.put(id, ci);
                return id;
            }).collect(Collectors.toList());
            TbkItemInfoGetRequest req = new TbkItemInfoGetRequest();
            req.setNumIids(String.join(",", itemIds));
            req.setPlatform(2L);

            try {
                TbkItemInfoGetResponse rsp = taobaoClient.execute(req);
                if (rsp.getResults() != null) {
                    for (TbkItemInfoGetResponse.NTbkItem nTbkItem : rsp.getResults()) {
                        CommissionItemSearchDTO dto = map.get(nTbkItem.getNumIid().toString());
                        if(dto == null) {
                            continue;
                        }
                        dto.setShopTitle(nTbkItem.getNick());
                        dto.setTitle(nTbkItem.getTitle());
                        dto.setFreeShipment(nTbkItem.getFreeShipment() == null ? 0 : 1);
                        dto.setTbkZt(nTbkItem.getMaterialLibType() != null && nTbkItem.getMaterialLibType().equals("1"));

                    }
                }
            } catch (ApiException e) {
                e.printStackTrace();
            }

        }
        logger.info("淘宝导购直接查询完成，总返回数量:" + paging.getResults().size());
        return paging;
    }

    public void bindToCommissionItemSearchBOPaging(Paging<CommissionItemSearchDTO> paging, Paging<CommissionItemFetchDTO> fetchBOPaging) {
        List<CommissionItemSearchDTO> searchBOS = new ArrayList<>();
        List<CommissionItemFetchDTO> cacheDtos = new ArrayList<>();
        for (CommissionItemFetchDTO ci : fetchBOPaging.getResults()) {
            CommissionItemSearchDTO bo = new CommissionItemSearchDTO();
            bo.setShareCommission(commissionItemService.findShareCommission(ci.getPrice(), ci.getCommissionRate()));
            bo.setCommissionRate(ci.getCommissionRate());
            bo.setCouponValue(ci.getCouponValue());
            bo.setEcomPlat(ci.getEcomPlat());
            bo.setFreeShipment(ci.isFreeShipment() ? 1 : 0);
            bo.setSourceItemId(ci.getSourceItemId());
            bo.setTitle(ci.getTitle());
            bo.setOriginPrice(ci.getOriginPrice());
            bo.setPicUrl(ci.getPicUrl());
            bo.setPrice(ci.getPrice());
            bo.setWhitePicUrl(ci.getWhitePicUrl());
            bo.setSales(ci.getSales());
            bo.setShopTitle(ci.getShopTitle());
            bo.setSourceItemUrl(ci.getSourceItemUrl());
            if (bo.getEcomPlat() == EcomPlat.TMALL || bo.getEcomPlat() == EcomPlat.TAOBAO) {
                cacheDtos.add(ci);
            }
            searchBOS.add(bo);
        }
        commissionItemService.cacheCommissionItemList(cacheDtos);
        logger.info("导购直接查询完成，查询结果数量:" + fetchBOPaging.getTotal());
        paging.setTotal(fetchBOPaging.getTotal());
        paging.setPage(fetchBOPaging.getPage());
        paging.setPageSize(fetchBOPaging.getPageSize());
        paging.setResults(searchBOS);
    }

    public Paging<CommissionItemSearchDTO> searchSite(SearchParam param) {

        Config config = new Config(Lists.newArrayList(openSearchConfig.getApp()));
        config.setStart((param.getPage() - 1) * param.getPageSize());
        config.setHits(param.getPageSize());
        //设置返回格式为fulljson格式
        config.setSearchFormat(SearchFormat.JSON);
        //创建参数对象
        SearchParams searchParams = new SearchParams(config);
        //指定搜索的关键词，这里要指定在哪个索引上搜索，如果不指定的话默认在使用“default”索引（索引字段名称是您在您的数据结构中的“索引字段列表”中对应字段。），
        //若需多个索引组合查询，需要在setQuery处合并，否则若设置多个setQuery子句，则后面的子句会替换前面子句
        List<String> queryParams = new ArrayList<>();
        if (StringUtils.isNotBlank(param.getKeywords())) {
            //queryParams.add(String.format("keywords:'%s'", param.getKeywords().replaceAll("['\"]", "")));
            String[] keys = param.getKeywords().split("[\\s\\n]");
            List<String> keyQueryParams = new ArrayList<>();
            for (String key : keys) {
                if (key.length() == 1) {
                    continue;
                }
                keyQueryParams.add(String.format("keywords:'%s'", key.replaceAll("['\"]", "")));
            }
            queryParams.add(String.format("(%s)", String.join(" OR ", keyQueryParams)));
        }
        if (param.getEcomPlat() != null) {
            if (param.getEcomPlat() == EcomPlat.TAOBAO) {
                queryParams.add("(ecom_plat:'TAOBAO' OR ecom_plat:'TMALL')");
            } else {
                queryParams.add(String.format("ecom_plat:'%s'", param.getEcomPlat().name()));
            }
        }

        if (StringUtils.isNotBlank(param.getCatIds())) {
            List<String> list = new ArrayList<>();
            String catIds;
            try {
                catIds = URLDecoder.decode(param.getCatIds(), "utf8");
            } catch (UnsupportedEncodingException e) {
                catIds = "";
                logger.error("解析catIds出错", param.getCatIds());
            }
            for (String s : catIds.split(",")) {
                ShopcatDTO shopcatDTO = shopcatService.findById(Long.valueOf(s));
                if (shopcatDTO != null && shopcatDTO.isSearchByKeyword()) {
                    String[] keys = shopcatDTO.getKeyword().split("[/\\s]");
                    List<String> keyQueryParams = new ArrayList<>();
                    for (String key : keys) {
                        keyQueryParams.add(String.format("keywords:'%s'", key));
                    }
                    queryParams.add(String.format("%s", String.join(" OR ", keyQueryParams)));
                    ShopcatDTO ref = shopcatDTO.getRef();
                    if (ref != null) {
                        list.add(String.format("shopcat_ids:'%s'", ref.getId()));
                    }
                } else {
                    list.add(String.format("shopcat_ids:'%s'", s));
                }
            }
            if (list.size() > 0) {
                if (list.size() == 1) {
                    queryParams.add(list.get(0));
                } else {
                    queryParams.add(String.format("(%s)", String.join(" OR ", list)));
                }
            }
        }

        if (param.getCatId() != null) {
            queryParams.add(String.format("shopcat_ids:'%s'", param.getCatId()));
        }

        if (StringUtils.isNotBlank(param.getChannelIds())) {
            List<String> list = new ArrayList<>();
            for (String s : param.getChannelIds().split(",")) {
                list.add(String.format("channel_ids:'%s'", s));
            }
            if (list.size() > 0) {
                if (list.size() == 1) {
                    queryParams.add(list.get(0));
                } else {
                    queryParams.add(String.format("(%s)", String.join(" OR ", list)));
                }
            }
        }

        if (param.getChannelId() != null) {
            queryParams.add(String.format("channel_ids:'%s'", param.getCatId()));
        }

        String query = String.join(" AND ", queryParams);
        searchParams.setQuery(StringUtils.isNotBlank(query) ? query : "''");
        Sort sort = new Sort();
        switch (param.getSort()) {
            case NONE:
                break;
            case PRICE_ASC:
                sort.addToSortFields(new SortField("price", Order.INCREASE));
                break;
            case PRICE_DESC:
                sort.addToSortFields(new SortField("price", Order.DECREASE));
                break;
            case SALES_DESC:
                sort.addToSortFields(new SortField("sales", Order.DECREASE));
                break;
            case LIST_TIME_DESC:
                sort.addToSortFields(new SortField("list_time", Order.DECREASE));
                break;
            case COMMISSION_VALUE_DESC:
                sort.addToSortFields(new SortField("price*commission_rate", Order.DECREASE));
                break;
        }
        searchParams.setSort(sort);
        List<String> filter = new ArrayList<>();
        if (param.getStartPrice() != null) {
            filter.add("price>=" + param.getStartPrice());
        }
        if (param.getEndPrice() != null) {
            filter.add("price<=" + param.getEndPrice());
        }
        if (param.getRecommend() != null) {
            filter.add("recommend=1");
        }
        if (param.getFreeShipment() != null && param.getFreeShipment()) {
            filter.add("free_shipment=1");
        }
        if (param.getJdSale() != null && param.getJdSale()) {
            filter.add("js_sale=1");
        }
        if (param.getMinCommissionFee() != null) {
            filter.add("price*commission_rate>" + param.getMinCommissionFee() * 100);
        }
        if (param.getMinSales() != null) {
            filter.add("sales>" + param.getMinSales());
        }
        if (filter.size() > 0) {
            searchParams.setFilter(String.join(" AND ", filter));
        }
        filter.add("delist_time>" + new Date().getTime());

        //设置查询过滤条件
        //searchParams.setFilter("type='UatmTbkItem'");
        //创建sort对象，并设置二维排序
        //Sort sort = new Sort();
        //设置id字段降序
        //sort.addToSortFields(new SortField("id", Order.DECREASE));
        //若id相同则以RANK相关性算分升序
        //sort.addToSortFields(new SortField("RANK", Order.INCREASE));
        //执行查询语句返回数据对象

        SearchResult searchResult = null;
        try {
            searchResult = searcherClient.execute(searchParams);
        } catch (Exception e) {
            logger.error("执行搜索出错", e);
        }
        //以字符串返回查询数据
        String result = searchResult.getResult();
        SearchResponse<CommissionItemSearchDTO> res = JSON.parseObject(result, new TypeReference<SearchResponse<CommissionItemSearchDTO>>() {
        });
        Paging<CommissionItemSearchDTO> paging = new Paging<>();
        paging.setResults(res.getResult().getItems());
        paging.setTotal(res.getResult().getTotal());
        paging.setPage(param.getPage());
        paging.setPageSize(param.getPageSize());
        return paging;
    }

    @Override
    public List<CommissionItemSearchDTO> findSameStyleById(long id, int size) {
        CommissionItemDTO dto = commissionItemService.findById(id);
        if (dto == null) {
            return new ArrayList<>();
        }
        SearchParam param = new SearchParam();
        if (dto.getShopcatId() != null) {
            param.setCatId(dto.getShopcatId());
        }
        param.setEcomPlat(dto.getEcomPlat());
        param.setPageSize(size);
        Paging<CommissionItemSearchDTO> paging = this.search(param);
        return paging.getResults();
    }

}
